﻿// ---------------------------------------------------------------------
// Lớp SSupervisor
//
// Nội dung:
//    + Lớp này là lớp quản lý lớn nhất, lớp trực tiếp giao tiếp với client
//
// Copyright (c) 2009 YugiOH
//
// Nguyễn Hữu Lê Trọng Tín      YM: ilu2009             ĐT: 0906520611 
// Võ Phước Hậu                 YM: phuochauspkt        ĐT: 0979202707
// ---------------------------------------------------------------------


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common;
using Yugi.Client.Card;
using System.Threading;
using System.Reflection;
using System.Net.Sockets;
using System.Net;
using ManagementEffect;
using ManagementEffect.Engine;
using ServerYuGi.Helper;
using APIEffect;
//using BYServer;
//using BYServer.SocketEventArgs;
using ServerYuGi.PythonRegister;
using ServerYuGi.CardScriptDatabase;
using System.IO;
using ServerYuGi.ChainEffectManager;
using ServerYuGi.Converter;
using Yugi.Client.WebSerive;

namespace ServerYuGi
{
    public partial class SSupervisor : ISupervisor
    {
        public STable Table; // chua su dung
        public List<SPlayer> Players = new List<SPlayer>();      
        public SGame Game = new SGame();
        public STurnManager TurnManager;
        
        //Tin : Replay Mode
        //public YServer ServerSocket;
        
        public ETurnManager EffectTurnManager = new ETurnManager();
        public APIManager api_manager;
        public PythonEngine engine = new PythonEngine();
        public ExcuteEffectManager ExEffectManager = new ExcuteEffectManager();
        public PYRegisterManager pyregister;
        public ChainManager ChainMnager;
        public CardScriptDB CScriptDB = new CardScriptDB();

        Random random = new Random();

        public static int port;
        public static string IP_SERVER;
        
  
        bool isLuotDau = true;

        public WaitForMeManager WaitManager = new WaitForMeManager();
        public RevMSGManager RevMSGmanager = new RevMSGManager();
        public FlagManager flagManager = new FlagManager();

        Queue<Action> QueueProcess;

        WebServiceCommunication yugiService;
        
        //------Event------------------//
        
       
        
        /// <summary>
        /// Constructor
        /// </summary>
        public SSupervisor(string pathConfig)
        {
            //ServerSocket = new YServer(pathConfig,Program.isTest);

            CScriptDB.LoadAllScript(Directory.GetCurrentDirectory() + "\\Table\\Script");
            YConverter.Cardpath = Directory.GetCurrentDirectory() + "\\Table\\player";
           
            QueueProcess = new Queue<Action>();
            ExEffectManager.Init();

            engine.SetAssembly(typeof(String).Assembly);
            engine.SetAssembly(typeof(YCheckPoint).Assembly);
            engine.SetAssembly(typeof(APIManager).Assembly);
            engine.SetAssembly(typeof(YMSG).Assembly);
            engine.SetAssembly(typeof(YNormalCard).Assembly);
            engine.SetCode("print 'Engine Init Complete'");
            engine.Excute();  
            TurnManager = new STurnManager(this);

            api_manager = new APIManager(this);
            pyregister = new PYRegisterManager(this);
            ChainMnager = new ChainManager(this);
            //ServerSocket = new YServer(); 

            //Tin: Rem b/c Replay don't nedd it
            //ServerSocket.XSocketConnected += new YServer.XSocketConnectedHandler(ServerSocket_XSocketConnected);
            Table = new STable();
            yugiService = new WebServiceCommunication();

        }

        private List<int>[] Fake_Card_Deck = new List<int>[2];
        public void Simulation_AddPlayer_Card(int id,List<int> cards)
        {
            Fake_Card_Deck[id] = cards;
        }

        public void Sumilation_AddPlayer(int id)
        {
            SPlayer player = new SPlayer();
            player.MyConnection = new YUser(id);
            player.ID = id;
            player.MySupervisor = this;
            Players.Add(player);
        }
       
        public void StartServer()
        {
            //ServerSocket.Start();
            ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessQueue));
            //Table.ID_Table = ServerSocket.GetTableID();
        }

        //Tin: Rem b/c Replay Mode don't need it
        //void ServerSocket_XSocketConnected(object sender, XSocketConnectedEventArgs args)
        //{
 
        //    args.user.XSocketRecive+=new YUser.XSocketReciveHandler(ServerSocket_XSocketRecive);
        //    args.user.XSocketDisconnected += new YUser.XSocketDisconnectedHandler(user_XSocketDisconnected);
           
        //}
        //Tin: Rem b/c Replay Mode don't need it

        //Tin: Rem b/c Replay Mode don't need it
        //void user_XSocketDisconnected(object sender, XSocketDisconnectEventArgs args)
        //{
        //    Process_PLAYER_LOGOUT(args.user.ID);
        //    ServerSocket.Kill(args.user);
        //}


        void ServerSocket_XSocketRecive(object sender, XSocketReciveEventArgs args)
        {
            if (Game.isPlaying && args.user.ID != TurnManager.IDPlayerTrongLuot && !RevMSGmanager.isPlayerKoTrongLuot)                           
                    return;
                
            YMSG message = (YMSG)args.Data[0];
            Console.WriteLine("Receive: " + message.ToString());

            //-------------------------Kiem Tra Message co trong Turn hien tai hay khong ------------------------//
            if (!CheckYMSG(message))
                return;
            Console.WriteLine("YMSG co trong Turn hien tai");
            //---------------------------------------------------------------------------------------------------//

            
            List<object> param = new List<object>();
            for (int i = 1; i < args.Data.Length; i++)
            {
                param.Add((int)args.Data[i]);
            }
            if (message == YMSG.PLAYER_LOGIN)
                param.Add((int)args.user.ID);
            if (message == YMSG.PLAYER_LOGOUT)
            {                
                                  
                return;
            }
            SendMessageToServer(message, param.ToArray());
        }        

        public void ProcessQueue(object obj)
        {
            while (true)
            {
                Monitor.Enter(QueueProcess);                
                
                Action item = null;
                if(QueueProcess.Count > 0)
                {
                    item = QueueProcess.Dequeue();
                    item();
                    Monitor.Exit(QueueProcess);
                }
                else
                {
                    Monitor.Exit(QueueProcess);
                    Thread.Sleep(30);
                }
                
                
            }
        }       

        #region ISupervisor Members

        public void SendMessageToServer(YMSG message, params object[] param)
        {

            Type t = typeof(SSupervisor);
            MethodInfo handler = t.GetMethod("Process_" + message.ToString(), BindingFlags.NonPublic | BindingFlags.Instance);

            //-----------------Kiểm tra message có phải là respone hay không vì server đang trong trạng thái chờ ---------------------//
            if (WaitManager.isWait)
            {              
                if (!RevMSGmanager.CheckYMSG_RESPONE(message))
                    return;
                else
                {
                    handler.Invoke(this, new object[] { param });
                    return;
                }
            }
            //-------------------------------------------------------------------------------------------------------------------------//
            if(RevMSGmanager.isPlayerKoTrongLuot)
            {
                if (!RevMSGmanager.CheckYMSG_RESPONE_KHONGTRONGLUOT(message))
                    return;
            }


            Action act = () =>
                {
                    //try
                    //{
                        handler.Invoke(this, new object[] { param });
                    //}
                    //catch (Exception ex)
                    //{
                     //   Console.WriteLine("------------------------------Loi YMSG." + message.ToString()+"----------------------------");
                    //}
                };

           
            Monitor.Enter(QueueProcess);    
            QueueProcess.Enqueue(act);
            Monitor.Exit(QueueProcess);
        }

        public void ReciveMessageFromServer(YMSG message, params object[] param)
        {
           
        }

        #endregion

        /// <summary>
        /// Lấy player đang không trong lượt
        /// </summary>
        /// <returns>player lấy được</returns>
        public SPlayer LayPlayerKhacVoiPlayerDangTrongLuot()
        {
            foreach (SPlayer item in Players)
            {
                if (item.ID != TurnManager.IDPlayerTrongLuot)
                    return item;
            }
            return null;
        }

        /// <summary>
        /// Lấy 1 player
        /// </summary>
        /// <param name="ID">ID player cần lấy</param>
        /// <returns>player lấy được</returns>
        public SPlayer LayPlayer(int ID)
        {
            foreach (SPlayer item in Players)
            {
                if (item.ID == ID)
                    return item;
            }
            return null;
        }
        public SPlayer LayPlayerKhacVoiID(int ID)
        {
            foreach (SPlayer item in Players)
            {
                if (item.ID != ID)
                    return item;
            }
            return null;
        }

        public SPlayer GetPlayerOwner(int IDCard)
        {
            SPlayer player = LayPlayer(TurnManager.IDPlayerTrongLuot);
            if (player.CheckIDInAll(IDCard))
                return player;
            SPlayer Other = LayPlayerKhacVoiID(player.ID);
            if (Other.CheckIDInAll(IDCard))
                return Other;
            return null;
        }

        public void F5()
        {
            TurnManager.F5();
            QueueProcess.Clear();
            isLuotDau = true;
            demPlayerBegin = 0;            
            EffectTurnManager.F5();
            ExEffectManager = new ExcuteEffectManager();
            ChainMnager.F5();
            WaitManager.F5();
            RevMSGmanager.Init();
            //pyregister.F5();
            pyregister = new PYRegisterManager(this);
            engine = new PythonEngine();
            engine.SetAssembly(typeof(String).Assembly);
            engine.SetAssembly(typeof(YCheckPoint).Assembly);
            engine.SetAssembly(typeof(APIManager).Assembly);
            engine.SetAssembly(typeof(YMSG).Assembly);
            engine.SetAssembly(typeof(YNormalCard).Assembly);
            engine.SetCode("print 'Engine Init Complete'");
            engine.Excute();
            Table = new STable();
            Game.F5();
            foreach (SPlayer player in Players)
            {
                player.F5();

            }
            
        }
        public void ClearQueueProcess()
        {
            Monitor.Enter(QueueProcess);
                QueueProcess.Clear();
            Monitor.Exit(QueueProcess);
        }






       

        
    }
}
